/*!
    \file  link32fa016bx_spih.h
    \brief definitions for the SPI Host

    \version 2024-01-09, V1.0.0, firmware for Link32FA016BX
*/

/*
    Copyright (c) 2024, LinkLiao(linkliao610@163.com)

*/

#ifndef LINK32FA016BX_SPIH_H
#define LINK32FA016BX_SPIH_H
#include "link32fa016bx.h"

LINK32FA016BX_BEGIN_DECLS

/* SPIHx(x=0,1) definitions */
#define SPIH0                            SPIH0_BASE
#define SPIH1                            SPIH1_BASE

/* SPI registers definitions */
#define SPIH_IS(spihx)                   REG32((spihx) + 0x00U) /*!< SPI interrupt state register */
#define SPIH_IE(spihx)                   REG32((spihx) + 0x04U) /*!< SPI interrupt enable register */
#define SPIH_IT(spihx)                   REG32((spihx) + 0x08U) /*!< SPI interrupt test register */
#define SPIH_AT(spihx)                   REG32((spihx) + 0x0CU) /*!< SPI alert test register */
#define SPIH_CTL(spihx)                  REG32((spihx) + 0x10U) /*!< SPI control register */
#define SPIH_STAT(spihx)                 REG32((spihx) + 0x14U) /*!< SPI status register */
#define SPIH_CFG(spihx)                  REG32((spihx) + 0x18U) /*!< SPI configuration register */
#define SPIH_CSID(spihx)                 REG32((spihx) + 0x1CU) /*!< SPI chip select id register */
#define SPIH_CMD(spihx)                  REG32((spihx) + 0x20U) /*!< SPI command register */
#define SPIH_RXD(spihx)                  REG32((spihx) + 0x24U) /*!< SPI receive data register */
#define SPIH_TXD(spihx)                  REG32((spihx) + 0x28U) /*!< SPI transmit data register */
#define SPIH_ERREN(spihx)                REG32((spihx) + 0x2CU) /*!< SPI error interrupt enable regster */
#define SPIH_ERRSTAT(spihx)              REG32((spihx) + 0x30U) /*!< SPI error status regster */
#define SPIH_EVENTEN(spihx)              REG32((spihx) + 0x34U) /*!< SPI event enable regster */

/* bits definitions */
/* SPIH_IS */
#define SPIH_IS_ERROR_Pos                0                                      /*!< error related interrupt pos */
#define SPIH_IS_ERROR_Msk                BIT(0)                                 /*!< error related interrupt mask */
#define SPIH_IS_EVENT_Pos                1                                      /*!< event related interrupt pos */
#define SPIH_IS_EVENT_Msk                BIT(1)                                 /*!< event related interrupt mask */

/* SPIH_IE */
#define SPIH_IE_ERROR_Pos                0                                      /*!< error related interrupt enable pos */
#define SPIH_IE_ERROR_Msk                BIT(0)                                 /*!< error related interrupt enable mask */
#define SPIH_IE_EVENT_Pos                1                                      /*!< event related interrupt enable pos*/
#define SPIH_IE_EVENT_Msk                BIT(1)                                 /*!< event related interrupt enable mask */

/* SPIH_IT */
#define SPIH_IT_ERROR_Pos                0                                      /*!< error related interrupt test pos */
#define SPIH_IT_ERROR_Msk                BIT(0)                                 /*!< error related interrupt test mask */
#define SPIH_IT_EVENT_Pos                1                                      /*!< event related interrupt test pos */
#define SPIH_IT_EVENT_Msk                BIT(1)                                 /*!< event related interrupt test mask */

/* SPIH_AT */
#define SPIH_AT_FATAL_Pos                0                                      /*!< write 1 to trigger one alert event of this kind */
#define SPIH_AT_FATAL_Msk                BIT(0)                                 /*!< write 1 to trigger one alert event of this kind */

/* SPIH_CTL */
#define SPIH_CTL_RX_WATERMASK_Pos        0                                      /*!<  */
#define SPIH_CTL_RX_WATERMASK_Msk        BITS(0,7)                              /*!<  */
#define SPIH_CTL_TX_WATERMASK_Pos        8                                      /*!<  */
#define SPIH_CTL_TX_WATERMASK_Msk        BITS(8,15)                             /*!<  */
#define SPIH_CTL_OUTPUT_EN_Pos           29                                     /*!< Enable the SPI host output buffers for the sck, csb and sd lines */
#define SPIH_CTL_OUTPUT_EN_Msk           BIT(29)                                /*!< Enable the SPI host output buffers for the sck, csb and sd lines */
#define SPIH_CTL_SW_RST_Pos              30                                     /*!< Reset the SPI Host */
#define SPIH_CTL_SW_RST_Msk              BIT(30)                                /*!< Reset the SPI Host */
#define SPIH_CTL_SPIEN_Pos               BIT(31)                                /*!< Enable the SPI host  */
#define SPIH_CTL_SPIEN_Msk               BIT(31)                                /*!< Enable the SPI host  */

/* SPIH_STAT */
#define SPIH_STAT_TXQD_Pos               0                                      /*!< TX Queue Depth */
#define SPIH_STAT_TXQD_Msk               BITS(0,7)                              /*!< TX Queue Depth */
#define SPIH_STAT_RXQD_Pos               8                                      /*!< RX Queue Depth */
#define SPIH_STAT_RXQD_Msk               BITS(8,15)                             /*!< RX Queue Depth */
#define SPIH_STAT_CMDQD_Pos               16                                    /*!< CMD Queue Depth */
#define SPIH_STAT_CMDQD_Msk               BITS(16,19)                           /*!< CMD Queue Depth */
#define SPIH_STAT_RXWM_Pos               20                                     /*!<  */
#define SPIH_STAT_RXWM_Msk               BIT(20)                                /*!<  */
#define SPIH_STAT_BYTEORDER_Pos          22                                     /*!<  */
#define SPIH_STAT_BYTEORDER_Msk          BIT(22)                                /*!<  */
#define SPIH_STAT_RXSTALL_Pos            23                                     /*!< indicates that an ongoing has stalled due to lack of available space in the RX FIFO */
#define SPIH_STAT_RXSTALL_Msk            BIT(23)                                /*!< indicates that an ongoing has stalled due to lack of available space in the RX FIFO */
#define SPIH_STAT_RXEMPTY_Pos            24                                     /*!< indicates that the receive fifo is empty */
#define SPIH_STAT_RXEMPTY_Msk            BIT(24)                                /*!< indicates that the receive fifo is empty */
#define SPIH_STAT_RXFULL_Pos             25                                     /*!< indicates that the receive fifo is full*/
#define SPIH_STAT_RXFULL_Msk             BIT(25)                                /*!< indicates that the receive fifo is full*/
#define SPIH_STAT_TXWM_Pos               26                                     /*!<  */
#define SPIH_STAT_TXWM_Msk               BIT(26)                                /*!<  */
#define SPIH_STAT_TXSTALL_Pos            27                                     /*!< indicates that an ongoing has stalled due to lack of data in the TX FIFO*/
#define SPIH_STAT_TXSTALL_Msk            BIT(27)                                /*!< indicates that an ongoing has stalled due to lack of data in the TX FIFO*/
#define SPIH_STAT_TXEMPTY_Pos            28                                     /*!< indicates that the transmit data fifo is empty */
#define SPIH_STAT_TXEMPTY_Msk            BIT(28)                                /*!< indicates that the transmit data fifo is empty */
#define SPIH_STAT_TXFULL_Pos             29                                     /*!< indicates that the transmit data fifo is full */
#define SPIH_STAT_TXFULL_Msk             BIT(29)                                /*!< indicates that the transmit data fifo is full */
#define SPIH_STAT_ACTIVE_Pos             30                                     /*!< indicates the SPI host is processing a previously issued command */
#define SPIH_STAT_ACTIVE_Msk             BIT(30)                                /*!< indicates the SPI host is processing a previously issued command */
#define SPIH_STAT_READY_Pos              31                                     /*!< indicates the SPI host is ready to receive commands  */
#define SPIH_STAT_READY_Msk              BIT(31)                                /*!< indicates the SPI host is ready to receive commands  */



/* SPIH_CFG */
#define SPIH_CFG_CLKDIV_Pos              0                                       /*!< Spi clock divider */
#define SPIH_CFG_CLKDIV_Msk              BITS(0,15)                              /*!< Spi clock divider */
#define SPIH_CFG_CSNIDLE_Pos             16                                      /*!< indicates the minimum number of sck half-cycles to hold cs_n high between commands */
#define SPIH_CFG_CSNIDLE_Msk             BITS(16,19)                             /*!< indicates the minimum number of sck half-cycles to hold cs_n high between commands */
#define SPIH_CFG_CSNTRAIL_Pos            20                                      /*!< */
#define SPIH_CFG_CSNTRAIL_Msk            BITS(20,23)                             /*!< */
#define SPIH_CFG_CSNLEAD_Pos             24                                      /*!< */
#define SPIH_CFG_CSNLEAD_Msk             BITS(24,27)                             /*!< */
#define SPIH_CFG_FULLCYC_Pos             29                                      /*!< */
#define SPIH_CFG_FULLCYC_Msk             BITS(29)                                /*!< */
#define SPIH_CFG_CPHA_Pos                30                                      /*!< The phase of sck clock relative to the data */
#define SPIH_CFG_CPHA_Msk                BITS(30)                                /*!< The phase of sck clock relative to the data */
#define SPIH_CFG_CPOL_Pos                31                                      /*!< The polarity of sck clock signal */
#define SPIH_CFG_CPOL_Msk                BIT(31)                                 /*!< The polarity of sck clock signal */


/* SPIH_CMD */
#define SPIH_CMD_LEN_Pos                 0                                       /*!< command length */
#define SPIH_CMD_LEN_Msk                 BITS(0,8)                               /*!< command length */
#define SPIH_CMD_CSAAT_Pos               9                                       /*!< Chip select active after transaction */
#define SPIH_CMD_CSAAT_Msk               BIT(9)                                  /*!< Chip select active after transaction */
#define SPIH_CMD_SPEED_Pos               10                                      /*!< 0:Standard SPI 1:Dual SPI 2:Quad SPI 3:Reserved */
#define SPIH_CMD_SPEED_Msk               BITS(10,11)                             /*!< 0:Standard SPI 1:Dual SPI 2:Quad SPI 3:Reserved */
#define SPIH_CMD_DIRECTION_Pos           12                                      /*!< 0:Dummy Cycles 1: Rx only 2:Tx only 3 Bidirectional Tx/Rx */
#define SPIH_CMD_DIRECTION_Msk           BITS(12,13)                             /*!< 0:Dummy Cycles 1: Rx only 2:Tx only 3 Bidirectional Tx/Rx */


/* SPIH_ERREN */
#define SPIH_ERREN_CMDBUSY_Pos           0                                       /*!< */
#define SPIH_ERREN_CMDBUSY_Msk           BIT(0)                                  /*!< */
#define SPIH_ERREN_OVERFLOW_Pos          1                                       /*!< */
#define SPIH_ERREN_OVERFLOW_Msk          BIT(1)                                  /*!< */
#define SPIH_ERREN_UNDERFLOW_Pos         2                                       /*!< */
#define SPIH_ERREN_UNDERFLOW_Msk         BIT(2)                                  /*!< */
#define SPIH_ERREN_CMDINVAL_Pos          3                                       /*!< */
#define SPIH_ERREN_CMDINVAL_Msk          BIT(3)                                  /*!< */
#define SPIH_ERREN_CSIDINVAL_Pos         4                                       /*!< */
#define SPIH_ERREN_CSIDINVAL_Msk         BIT(4)                                  /*!< */

/* SPIH_ERRSTAT */
#define SPIH_ERRSTAT_CMDBUSY_Pos         0                                       /*!< */
#define SPIH_ERRSTAT_CMDBUSY_Msk         BIT(0)                                  /*!< */
#define SPIH_ERRSTAT_OVERFLOW_Pos        1                                       /*!< */
#define SPIH_ERRSTAT_OVERFLOW_Msk        BIT(1)                                  /*!< */
#define SPIH_ERRSTAT_UNDERFLOW_Pos       2                                       /*!< */
#define SPIH_ERRSTAT_UNDERFLOW_Msk       BIT(2)                                  /*!< */
#define SPIH_ERRSTAT_CMDINVAL_Pos        3                                       /*!< */
#define SPIH_ERRSTAT_CMDINVAL_Msk        BIT(3)                                  /*!< */
#define SPIH_ERRSTAT_CSIDINVAL_Pos       4                                       /*!< */
#define SPIH_ERRSTAT_CSIDINVAL_Msk       BIT(4)                                  /*!< */
#define SPIH_ERRSTAT_ACCESSINVAL_Pos     5                                       /*!< */
#define SPIH_ERRSTAT_ACCESSINVAL_Msk     BIT(5)                                  /*!< */


/* SPIH_EVENTEN */
#define SPIH_EVENTEN_RXFULL_Pos          0                                       /*!< */
#define SPIH_EVENTEN_RXFULL_Msk          BIT(0)                                  /*!< */
#define SPIH_EVENTEN_TXEMPTY_Pos         1                                       /*!< */
#define SPIH_EVENTEN_TXEMPTY_Msk         BIT(1)                                  /*!< */
#define SPIH_EVENTEN_RXWM_Pos            2                                       /*!< */
#define SPIH_EVENTEN_RXWM_Msk            BIT(2)                                  /*!< */
#define SPIH_EVENTEN_TXWM_Pos            3                                       /*!< */
#define SPIH_EVENTEN_TXWM_Msk            BIT(3)                                  /*!< */
#define SPIH_EVENTEN_READY_Pos           4                                       /*!< */
#define SPIH_EVENTEN_READY_Msk           BIT(4)                                  /*!< */
#define SPIH_EVENTEN_IDLE_Pos            5                                       /*!< */
#define SPIH_EVENTEN_IDLE_Msk            BIT(5)                                  /*!< */


/* constants definitions */
/* SPIH  struct definitions */
typedef struct {
    uint32_t spi_pol_pha;                                                       /*!< SPI CPOL and CPHA */
    uint32_t csn_lead_time;                                                     /*!< Indicates the number of half sck cycles between the falling edge of csn and the first edge of sck */
    uint32_t csn_tail_time;                                                     /*!< Indicates the number of half sck cycles between the last edge of sck and raising edge of csn*/
    uint32_t csn_idle_time;                                                     /*!< Indicates the number of half sck cycles between commands*/
    uint32_t clk_div;                                                           /*!< sck clock divide factor */
} spih_parameter_struct;

typedef struct {
    uint32_t dir;                                                              /*!< Command Direction */
    uint32_t speed;                                                            /*!< Command Speed */
    uint32_t csnat;                                                            /*!< Chip select after transaction*/
    uint32_t len;                                                              /*!< Command Length */
} spih_command_struct;


#define SPIH_CK_PL_LOW_PH_1EDGE          0x0                                   /*!< SPI clock polarity is low level and phase is first edge */
#define SPIH_CK_PL_LOW_PH_2EDGE          0x1                                   /*!< SPI clock polarity is low level and phase is second edge */
#define SPIH_CK_PL_HIGH_PH_1EDGE         0x2                                   /*!< SPI clock polarity is high level and phase is first edge */
#define SPIH_CK_PL_HIGH_PH_2EDGE         0x3                                   /*!< SPI clock polarity is high level and phase is second edge */

#define SPIH_CMD_DIR_DUMMY               0x0
#define SPIH_CMD_DIR_RX_ONLY             0x1
#define SPIH_CMD_DIR_TX_ONLY             0x2
#define SPIH_CMD_DIR_RX_TX               0x3

#define SPIH_CMD_SPEED_SPI                 0x0
#define SPIH_CMD_SPEED_DPI                 0x1
#define SPIH_CMD_SPEED_QPI                 0x2

#define SPIH_CMD_CSN_ACTIVE              0x1
#define SPIH_CMD_CSN_INACTIVE            0x0


/* function declarations */
/* SPI Host deinitialization and initialization functions */
void spih_deinit(uint32_t spih_periph);
/* initialize the parameters of SPI Host struct with the default values */
void spih_struct_para_init(spih_parameter_struct* spih_struct);
/* initialize SPI parameter */
void spih_init(uint32_t spih_periph, spih_parameter_struct* spih_struct);
/* enable SPI */
void spih_enable(uint32_t spih_periph);
/* disable SPI */
void spih_disable(uint32_t spih_periph);

/* SPI lines functions */
void spih_lines_enable(uint32_t spih_periph);
void spih_lines_disable(uint32_t spih_periph);


/* normal mode communication */
/* SPI start a transaction command */
void spih_set_command(uint32_t spih_periph, spih_command_struct *spih_cmd);
/* SPI transmit data */
void spih_data_transmit(uint32_t spih_periph, uint32_t data);
/* SPI receive data */
uint32_t spih_data_receive(uint32_t spih_periph);
uint32_t spih_data_transceive(uint32_t spih_periph, uint32_t data);
void spih_waiting_for_end(uint32_t spih_periph);


LINK32FA016BX_END_DECLS

#endif /* LINK32FA016BX_SPI_H */
